﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Media.Imaging;

namespace LpbPrj.Client.Tools.Helper
{
    public class GDIPlusImage : IDisposable
    {
        [DllImport("Gdi32.dll")]
        private static extern bool DeleteObject(IntPtr hObject);

        private BufferedGraphicsContext context = null;
        private BufferedGraphics grafx = null;
        private System.Drawing.Bitmap bmp = null;
        private float scaleX = 1.0f;
        private float scaleY = 1.0f;
        private int lineLength = 0;
        private Pen pen = new Pen(Color.FromArgb(100, 0, 255, 0), 1);
        private IntPtr hBitmap = IntPtr.Zero;
        private Graphics bmpGraphics = null;

        public BitmapSource DrawToBuffer(short[] lines, int width, int height, int lineDataMax = 3072, int step = 1)
        {
            if (context == null)
            {
                context = BufferedGraphicsManager.Current;
                context.MaximumBuffer = new Size(width + 1, height + 1);
            }
            if (bmp == null)
            {
                bmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                bmp.MakeTransparent(Color.Transparent);
                bmpGraphics = Graphics.FromImage(bmp);
                bmpGraphics.FillRectangle(Brushes.Transparent, 0, 0, bmp.Width, bmp.Height);
            }

            //if (grafx != null) grafx.Dispose();
            if (grafx == null)
            {
                grafx = context.Allocate(bmpGraphics, new Rectangle(0, 0, width, height));
            }

            if (lines != null && lines.Length > 0 && lineLength != lines.Length)
            {
                scaleX = (float)(width * 1.0 / lines.Length);
                scaleY = (float)(height * 1.0 / lineDataMax);
                lineLength = lines.Length;
            }

            // Clear the graphics buffer every five updates. 
            grafx.Graphics.FillRectangle(Brushes.Black, 0, 0, bmp.Width, bmp.Height);

            // Draw randomly positioned and colored ellipses. 
            int counter = 0;
            int maxValue = 0;
            int maxNextValue = 0;
            for (int i = 0; i < lines.Length - 1; i++)
            {
                if (lines[i] > maxValue)
                    maxValue = lines[i];

                if (lines[i + 1] > maxNextValue)
                    maxNextValue = lines[i + 1];

                var hValue = Math.Min(maxValue, lineDataMax);
                var hNextValue = Math.Min(maxNextValue, lineDataMax);

                counter++;

                if (counter % step == 0)
                {
                    maxValue = 0;
                    maxNextValue = 0;
                    grafx.Graphics.DrawLine(pen, i * scaleX, height - hValue * scaleY, (i + 1) * scaleX, height - hNextValue * scaleY);
                }
            }

            grafx.Render(bmpGraphics);

            if (hBitmap != IntPtr.Zero) DeleteObject(hBitmap);
            hBitmap = bmp.GetHbitmap(Color.Transparent);
            var bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            return bitmapSource;
        }

        public BitmapSource DrawToBuffer(byte[] rawValues, int width, int height, System.Drawing.Imaging.ColorPalette bmpGay8Palette, System.Drawing.Imaging.PixelFormat pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
        {
            bmp = ImageShareHelper.Bytes2Bitmap(rawValues, width, height, bmpGay8Palette, pixelFormat);
            if (hBitmap != IntPtr.Zero) DeleteObject(hBitmap);
            hBitmap = bmp.GetHbitmap(Color.Transparent);
            var bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            return bitmapSource;
        }

        public void Dispose()
        {
            if (hBitmap != IntPtr.Zero) DeleteObject(hBitmap);
            if (grafx != null) grafx.Dispose();
            if (bmpGraphics != null) bmpGraphics.Dispose();
            if (bmp != null) bmp.Dispose();
            if (context != null) context.Dispose();
        }
    }
}
